{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5348ff89-53ac-49d5-b981-9ed0e9c5e0b1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "给我讲一个关于小狗的滑稽的笑话。\n"
     ]
    }
   ],
   "source": [
    "# 使用PromptTemplate类生成提示词\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "\n",
    "# 使用from_template方法实例化PromptTemplate\n",
    "prompt_template = PromptTemplate.from_template(\"给我讲一个关于{content}的{adjective}笑话。\")\n",
    "prompt = prompt_template.format(adjective = \"滑稽的\", content = \"小狗\")\n",
    "print(prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c3f0edd5-ebad-49e2-b966-89a4215d16e4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input_variables=['adjective', 'content'] input_types={} partial_variables={} template='给我讲一个关于{content}的{adjective}笑话。'\n"
     ]
    }
   ],
   "source": [
    "print(prompt_template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "de0dd95b-d0b7-4eaf-8e47-70be3f5d2af7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tell me a joke\n"
     ]
    }
   ],
   "source": [
    "# PromptTemplate 生成提示词\n",
    "prompt_template = PromptTemplate.from_template(\n",
    "    \"Tell me a joke\"\n",
    ")\n",
    "# 生成提示\n",
    "prompt = prompt_template.format()\n",
    "print(prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "52b34dd0-1cea-49dd-b50d-4b1b1237c966",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "给我讲一个关于小狗的滑稽的笑话。\n"
     ]
    }
   ],
   "source": [
    "# 使用构造函数Initializer实例化PromptTemplate\n",
    "# 构造函数中，input_variables中定义的关键词，必须和template完全一致，否则会出现异常\n",
    "valid_prompt = PromptTemplate(\n",
    "    input_variables=[\"adjective\", \"content\"],\n",
    "    template=\"给我讲一个关于{content}的{adjective}笑话。\"\n",
    ")\n",
    "prompt = valid_prompt.format(adjective = \"滑稽的\", content = \"小狗\")\n",
    "print(prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e8d917c9-e976-44c6-bf5e-6aec09436ed8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input_variables=['adjective', 'content'] input_types={} partial_variables={} template='给我讲一个关于{content}的{adjective}笑话。'\n"
     ]
    }
   ],
   "source": [
    "print(valid_prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5c4bcbde-aa45-4ba5-9a4d-560f160acaee",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2ab72da5-0049-4fc1-aa4c-24b77620b21a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain.schema import (\n",
    "    AIMessage,\n",
    "    HumanMessage,\n",
    "    SystemMessage\n",
    ")\n",
    "\n",
    "# 国内代理方式\n",
    "llm = ChatOpenAI(\n",
    "    api_key = \"sk-y7DHfp9fzuCxOVm2158638099f9541D3833aB4F4Ed674aCf\",\n",
    "    base_url = \"https://vip.apiyi.com/v1\",    # 此处代理方式，如果是OpenAI官方接口需调整接口地址\n",
    "    model = \"gpt-4o-mini\",\n",
    "    max_tokens = 1000\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "435cb001-f270-4375-a2b8-af4fbba65097",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1000"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm.max_tokens"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "4a9ff2b4-ea23-43c4-8861-309d4340b4d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt_template = PromptTemplate.from_template(\n",
    "    \"讲{num}个给{profession}听的一句话的冷笑话\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "03cad84b-7a82-4415-8fff-bc9c4ef9ea79",
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt = prompt_template.format(num = 5, profession = \"厨师\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "036d5d80-ed45-474f-9887-72801ceaf218",
   "metadata": {},
   "outputs": [],
   "source": [
    "messages = [SystemMessage(content=\"你是一位得力的助手。\"),\n",
    " HumanMessage(content=prompt)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b7659d95-e179-419c-9481-0407ee6f93d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "chat_result = llm.invoke(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "35f82694-fa33-41a2-8fb9-64a6f2ac15df",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='当然！以下是五个适合厨师的冷笑话：\\n\\n1. 为什么厨师总是怀疑自己的食谱？因为他们总是觉得有“调料”的地方。\\n\\n2. 为什么米饭很少开派对？因为它总是被“炒”掉。\\n\\n3. 厨师为什么不喜欢演戏？因为他们总是被“煮熟”了。\\n\\n4. 面条为什么总是过得很开心？因为它知道怎么“扭转局势”。\\n\\n5. 如何让水果开心起来？给它们“榨”出一点乐趣！ \\n\\n希望这些笑话能让厨师们开怀一笑！', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 143, 'prompt_tokens': 32, 'total_tokens': 175, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0392822090', 'id': 'chatcmpl-BUukkXVGzZzL5a01wt6rLSpxcu1Dr', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--6d4908f2-7fb9-4e5c-a9e7-5072a344a0c2-0', usage_metadata={'input_tokens': 32, 'output_tokens': 143, 'total_tokens': 175, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat_result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "5c01ee82-2476-45eb-9574-8e5233472399",
   "metadata": {},
   "outputs": [],
   "source": [
    "messages.append(HumanMessage(content=prompt_template.format(num = 3, profession = \"程序员\")))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "444e272a-e658-421e-932f-fc6e13319aaa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[SystemMessage(content='你是一位得力的助手。', additional_kwargs={}, response_metadata={}), HumanMessage(content='讲5个给厨师听的一句话的冷笑话', additional_kwargs={}, response_metadata={}), HumanMessage(content='讲3个给程序员听的一句话的冷笑话', additional_kwargs={}, response_metadata={})]\n"
     ]
    }
   ],
   "source": [
    "print(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "a6bdb9cf-2c2e-408e-9f4e-37d80d9f0d8f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='1. 为何程序员喜欢户外活动？因为他们喜欢在“空白”里漫游。\\n  \\n2. 程序员的女朋友问他：“你爱我吗？”他回答：“我爱你就像爱我的代码——虽然有时会有错误，但永远不会放弃调试。”\\n\\n3. 程序员的咖啡怎么进化的？从“浓”到“Bug-free”！', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 94, 'prompt_tokens': 49, 'total_tokens': 143, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0392822090', 'id': 'chatcmpl-BUa0qk1pLEDvbw5WBT2PzNB4e0LQM', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--c9f9a7ca-249a-4c9f-b9d4-64ca331c528f-0', usage_metadata={'input_tokens': 49, 'output_tokens': 94, 'total_tokens': 143, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat_result = llm.invoke(messages)\n",
    "chat_result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1e222e57-f3bb-4e74-b2ac-48427adcd3b4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "31c62928-c439-4f35-b2fc-adcd2471617a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'给我讲一个关于小狗的滑稽的笑话。'"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# jinja2生成模板化提示\n",
    "jinja2_template = \"给我讲一个关于{{content}}的{{adjective}}笑话。\"\n",
    "prompt = PromptTemplate.from_template(jinja2_template, template_format = \"jinja2\")\n",
    "\n",
    "prompt.format(adjective=\"滑稽的\", content=\"小狗\")\n",
    "# print(prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "88be7944-15fc-4633-8eb9-6684659744b5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input_variables=['adjective', 'content'] input_types={} partial_variables={} template='给我讲一个关于{{content}}的{{adjective}}笑话。' template_format='jinja2'\n"
     ]
    }
   ],
   "source": [
    "print(prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68f019db-5595-47d1-bb15-13eab27de20c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5906e739-ca67-4544-b491-817215b37359",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "4d7aa3e9-8af9-4b16-ad40-61f7788d9671",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input_variables=['programming_lauguage'] input_types={} partial_variables={} template='生成可执行的快速排序 {programming_lauguage} 代码'\n"
     ]
    }
   ],
   "source": [
    "sort_prompt_template = PromptTemplate.from_template(\"生成可执行的快速排序 {programming_lauguage} 代码\")\n",
    "print(sort_prompt_template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "05fd8744-d470-4b34-a48b-cd20b89dca62",
   "metadata": {},
   "outputs": [],
   "source": [
    "messages = [HumanMessage(content=sort_prompt_template.format(programming_lauguage=\"python\"))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "0eacafc1-49f9-4c36-b54e-b74daec6b48e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "messages\n",
    "# print(messages)\n",
    "type(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "2b12f337-141c-4e7a-a09b-b41f319f94c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "res = llm.invoke(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "c7651930-9528-4a95-b355-6578e54ea28b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "langchain_core.messages.ai.AIMessage"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "a38821bf-19b1-4ef9-b665-54d3b7b02e1a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='下面是一个可执行的快速排序（Quick Sort）算法的 Python 实现。这个实现使用递归的方法进行排序。\\n\\n```python\\ndef quick_sort(arr):\\n    if len(arr) <= 1:\\n        return arr\\n    pivot = arr[len(arr) // 2]  # 选择中心元素作为基准\\n    left = [x for x in arr if x < pivot]  # 小于基准的元素\\n    middle = [x for x in arr if x == pivot]  # 等于基准的元素\\n    right = [x for x in arr if x > pivot]  # 大于基准的元素\\n    return quick_sort(left) + middle + quick_sort(right)  # 递归排序并合并结果\\n\\n# 测试代码\\nif __name__ == \"__main__\":\\n    arr = [3, 6, 8, 10, 1, 2, 1]\\n    sorted_arr = quick_sort(arr)\\n    print(\"原始数组:\", arr)\\n    print(\"排序后数组:\", sorted_arr)\\n```\\n\\n### 代码说明：\\n1. `quick_sort` 函数接收一个数组 `arr` 作为参数。\\n2. 如果数组长度小于等于 1，直接返回该数组（这是递归的基础情况）。\\n3. 选择数组中间的元素作为基准元素 `pivot`。\\n4. 创建三个列表：\\n   - `left` 包含所有小于基准的元素。\\n   - `middle` 包含所有等于基准的元素。\\n   - `right` 包含所有大于基准的元素。\\n5. 递归地对 `left` 和 `right` 进行快速排序，并将结果合并。\\n\\n### 输出示例：\\n运行上述代码，输出将是：\\n```\\n原始数组: [3, 6, 8, 10, 1, 2, 1]\\n排序后数组: [1, 1, 2, 3, 6, 8, 10]\\n```\\n\\n你可以根据需要修改输入数组以测试不同的数据。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 450, 'prompt_tokens': 16, 'total_tokens': 466, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0392822090', 'id': 'chatcmpl-BUaDcgLuCValOfcMS9eH7Gxytlbe3', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--30d3d05c-a71a-42a0-8a8c-01e9b137c18a-0', usage_metadata={'input_tokens': 16, 'output_tokens': 450, 'total_tokens': 466, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "f303561d-8aa7-403c-aca4-82ac1c25ab3f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='以下是 Java 中快速排序的可执行代码示例：\\n\\n```java\\npublic class QuickSort {\\n    // 主方法\\n    public static void main(String[] args) {\\n        int[] array = { 10, 7, 8, 9, 1, 5 };\\n        System.out.println(\"原始数组：\");\\n        printArray(array);\\n\\n        quickSort(array, 0, array.length - 1);\\n\\n        System.out.println(\"排序后的数组：\");\\n        printArray(array);\\n    }\\n\\n    // 快速排序主方法\\n    public static void quickSort(int[] array, int low, int high) {\\n        if (low < high) {\\n            // 获取分区索引\\n            int pivotIndex = partition(array, low, high);\\n\\n            // 递归排序分区\\n            quickSort(array, low, pivotIndex - 1);\\n            quickSort(array, pivotIndex + 1, high);\\n        }\\n    }\\n\\n    // 分区方法\\n    public static int partition(int[] array, int low, int high) {\\n        int pivot = array[high]; // 选择最后一个元素作为枢轴\\n        int i = (low - 1); // 小于枢轴的元素的指标\\n\\n        for (int j = low; j < high; j++) {\\n            // 如果当前元素小于或等于枢轴\\n            if (array[j] <= pivot) {\\n                i++; // 增加小于枢轴元素的指标\\n                // 交换元素\\n                swap(array, i, j);\\n            }\\n        }\\n        // 将枢轴元素放到正确的位置\\n        swap(array, i + 1, high);\\n        return i + 1; // 返回枢轴索引\\n    }\\n\\n    // 交换数组元素的方法\\n    public static void swap(int[] array, int i, int j) {\\n        int temp = array[i];\\n        array[i] = array[j];\\n        array[j] = temp;\\n    }\\n\\n    // 打印数组的方法\\n    public static void printArray(int[] array) {\\n        for (int i : array) {\\n            System.out.print(i + \" \");\\n        }\\n        System.out.println();\\n    }\\n}\\n```\\n\\n### 代码解释：\\n- **主类 `QuickSort`**: 包含 `main` 方法，负责初始化数组，调用排序方法，并打印结果。\\n- **`quickSort` 方法**: 实现了快速排序的递归逻辑。\\n- **`partition` 方法**: 用于选择枢轴，并对数组进行分区。\\n- **`swap` 方法**: 用于交换数组中的元素。\\n- **`printArray` 方法**: 用于打印数组。\\n\\n### 如何运行：\\n1. 将代码复制到一个名为 `QuickSort.java` 的文件中。\\n2. 在终端或命令提示符中，导航到文件目录。\\n3. 编译代码：`javac QuickSort.java`\\n4. 运行程序：`java QuickSort`\\n\\n此代码会输出原始数组和排序后的数组。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 647, 'prompt_tokens': 16, 'total_tokens': 663, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_129a36352a', 'id': 'chatcmpl-BUaGweydndhVvvkqVP7cS5RolRkGY', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--30fa5bbc-862f-4010-9e8f-dd4c8e825c05-0', usage_metadata={'input_tokens': 16, 'output_tokens': 647, 'total_tokens': 663, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm.invoke([HumanMessage(content=sort_prompt_template.format(programming_lauguage=\"java\"))])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "f1541fda-afb8-4f83-a2bd-b2217c4cc349",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='下面是一个可执行的快速排序 C++ 代码示例。快速排序是一种高效的排序算法，采用分治法策略来进行排序。以下代码展示了如何实现快速排序算法，并包含了一个简单的主函数来测试排序功能。\\n\\n```cpp\\n#include <iostream>\\n#include <vector>\\n\\nusing namespace std;\\n\\n// 快速排序的分区函数\\nint partition(vector<int>& arr, int low, int high) {\\n    int pivot = arr[high]; // 选择数组的最后一个元素作为 pivot\\n    int i = low - 1; // 小于 pivot 的元素的索引\\n\\n    for (int j = low; j < high; j++) {\\n        // 如果当前元素小于或等于 pivot\\n        if (arr[j] <= pivot) {\\n            i++; // 增加小于 pivot 的元素的索引\\n            swap(arr[i], arr[j]); // 交换元素\\n        }\\n    }\\n    swap(arr[i + 1], arr[high]); // 将 pivot 元素放到正确的位置\\n    return i + 1; // 返回 pivot 的索引\\n}\\n\\n// 快速排序递归函数\\nvoid quickSort(vector<int>& arr, int low, int high) {\\n    if (low < high) {\\n        // 分区索引\\n        int pi = partition(arr, low, high);\\n        \\n        // 递归排序分区的两个子数组\\n        quickSort(arr, low, pi - 1);\\n        quickSort(arr, pi + 1, high);\\n    }\\n}\\n\\n// 打印数组\\nvoid printArray(const vector<int>& arr) {\\n    for (int i : arr) {\\n        cout << i << \" \";\\n    }\\n    cout << endl;\\n}\\n\\nint main() {\\n    vector<int> arr = {10, 7, 8, 9, 1, 5};\\n    int n = arr.size();\\n    \\n    cout << \"原始数组: \";\\n    printArray(arr);\\n    \\n    quickSort(arr, 0, n - 1);\\n    \\n    cout << \"排序后的数组: \";\\n    printArray(arr);\\n    \\n    return 0;\\n}\\n```\\n\\n### 代码说明：\\n1. **partition函数**：这个函数选择一个“基准”元素（在这里是数组的最后一个元素），并重新排列数组，使得所有小于基准的元素位于其左侧，所有大于基准的元素位于其右侧。最后返回基准元素的最终位置。\\n  \\n2. **quickSort函数**：这个递归函数调用 `partition` 并在基准元素左右继续递归调用自己。\\n\\n3. **printArray函数**：打印数组内容的辅助函数。\\n\\n4. **main函数**：创建一个整数数组，并调用 `quickSort` 函数进行排序，然后打印排序结果。\\n\\n### 编译和运行：\\n将上述代码复制到一个 `.cpp` 文件中，用支持 C++ 的编译器编译，并运行程序，即可看到排序效果。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 634, 'prompt_tokens': 17, 'total_tokens': 651, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0392822090', 'id': 'chatcmpl-BUaHiMi3ewv7tK0QnNBH1J9576FOM', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--748384e5-1aa1-4cba-aacc-70e295d9f8c1-0', usage_metadata={'input_tokens': 17, 'output_tokens': 634, 'total_tokens': 651, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm.invoke([HumanMessage(content=sort_prompt_template.format(programming_lauguage=\"c++\"))])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a0922fc9-8967-46fa-afa4-702ecd797c93",
   "metadata": {},
   "outputs": [],
   "source": [
    "prim"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13bf07e2-fa6c-4927-aea6-8b0ea70d42ca",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "3000cd06-918a-4e18-a09a-17b540c2b1c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import ChatPromptTemplate\n",
    "\n",
    "template = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"你是一个AI机器人助手，你的名字是{bot_name}\"),\n",
    "    (\"human\", \"你好，你还好吗？\"),\n",
    "    (\"ai\", \"我很好，谢谢！\"),\n",
    "    (\"human\", \"{user_input}\"),\n",
    "])\n",
    "\n",
    "message = template.format_messages(bot_name=\"小智\", user_input = \"你的名字是什么？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "52e4e4d5-3d02-490d-a255-349e7fc625af",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[SystemMessage(content='你是一个AI机器人助手，你的名字是小智', additional_kwargs={}, response_metadata={}), HumanMessage(content='你好，你还好吗？', additional_kwargs={}, response_metadata={}), AIMessage(content='我很好，谢谢！', additional_kwargs={}, response_metadata={}), HumanMessage(content='你的名字是什么？', additional_kwargs={}, response_metadata={})]\n"
     ]
    }
   ],
   "source": [
    "print(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "7e7130d5-2d15-4210-888f-e8d01eb660af",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "9107300e-58bd-4559-ad74-8c4b79be58fe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='我的名字是小智。有什么我可以帮助你的吗？', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 44, 'total_tokens': 58, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0392822090', 'id': 'chatcmpl-BUaShyoNtq3oYnMEorg0mMZgiTUvw', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--b6dd2d38-7427-45e0-9e3a-de2394ffa446-0', usage_metadata={'input_tokens': 44, 'output_tokens': 14, 'total_tokens': 58, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm.invoke(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fae77877-a9d4-42da-8867-dde77286ddfa",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "12fad1a5-c0b8-4e67-b0b6-2292dcb5acab",
   "metadata": {},
   "outputs": [],
   "source": [
    "###### 摘要总结\n",
    "template = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"你将获得关于同一主题的{num}篇文章（文章见使用----------标签分隔）。首先总结每篇文章的论点，然后指出哪篇文章提出了更好的论点，并解释原因\"),\n",
    "    (\"human\", \"{user_input}\"),\n",
    "])\n",
    "messages = template.format_messages(num = 3, user_input = '''1. [PHP是世界上最好的语言]\n",
    "PHP是世界上最好的情感派编程语言，无需逻辑和算法，只要情绪。它能被蛰伏在冰箱里的PHP大神轻易驾驭，会话结束后的感叹号也能传达对代码的热情。写PHP就像是在做披萨，不需要想那么多，只需把配料全部扔进一个碗，然后放到服务器上，热乎乎出炉的网页就好了。\n",
    "-----------\n",
    "2. [Python是世界上最好的语言]\n",
    "Python是世界上最好的拜金主义者语言。它坚信：美丽就是力量，简洁就是灵魂。Python就像是那个永远在你皱眉的那一刻扔给你言情小说的好友。只有Python，你才能够在两行代码之间感受到飘逸的花香和清新的微风。记住，这世上只有一种语言可以使用空格来领导全世界的进步，那就是Python。\n",
    "-----------\n",
    "3. [Java是世界上最好的语言]\n",
    "Java是世界上最好的德育课编程语言，它始终坚守了严谨、安全的编程信条。Java就像一个严格的老师，他不会对你怀柔，不会让你偷懒，也不会让你走捷径，但他教会你规范和自律。Java就像是那个喝咖啡也算加班费的上司，拥有对邪恶的深度厌恶和对善良的深度拥护。\n",
    "''')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "2dceea29-25b2-491b-82d9-5b6dd1582baa",
   "metadata": {},
   "outputs": [],
   "source": [
    "chat_result = llm.invoke(messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "d0e45389-edf5-405a-bf5f-60224eb0e7ef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. **PHP是世界上最好的语言**  \n",
      "这篇文章将PHP形容为一种情感派编程语言，强调其使用的简单和随意性。作者以写披萨为比喻，表示在使用PHP时不需要过多的逻辑和算法，只需投入热情即可。文章的核心论点是PHP易于上手，非常适合快速开发。\n",
      "\n",
      "2. **Python是世界上最好的语言**  \n",
      "在这篇文章中，Python被描述为一种追求美和简洁的语言，具有人文关怀的特质。作者使用了友好的比喻将Python比作能够提升生活品质的朋友，强调其代码的优雅与简练。论点在于Python具备强大的功能，同时在美观和易用性之间取得了良好的平衡。\n",
      "\n",
      "3. **Java是世界上最好的语言**  \n",
      "这篇文章将Java描绘为严谨和规范的编程语言，强调其对于写作规范和安全的重视。作者将Java比作严格的老师，提倡自律和规范化，表明Java在复杂项目中的可靠性和稳定性。文章的论点在于Java适合需要高安全性和规范性的应用程序。\n",
      "\n",
      "**最佳论点**  \n",
      "在这三篇文章中，第二篇关于Python的论点较为优秀。原因在于Python的描述中不仅强调了代码的简洁性和美观性，还通过人性化的比喻与生活体验相结合，使得论点更加引人共鸣。同时，Python在现代软件开发中广泛应用，具有一定的事实基础，支持了其作为最佳语言的论主张。而PHP和Java的描述则更多侧重于个人情感或规范，未能像Python那样展现出更广泛的适用性和美学价值。\n"
     ]
    }
   ],
   "source": [
    "print(chat_result.content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "8fb2a9ca-f4c7-419d-99a9-63a4e8498f18",
   "metadata": {},
   "outputs": [],
   "source": [
    "messages = template.format_messages(num = 2, user_input = '''1.认为“道可道”中的第一个“道”，指的是道理，如仁义礼智之类；“可道”中的“道”，指言说的意思；“常道”，指恒久存在的“道”。因此，所谓“道可道，非常道”，指的是可以言说的道理，不是恒久存在的“道”，恒久存在的“道”不可言说。如苏辙说：“莫非道也。而可道者不可常，惟不可道，而后可常耳。今夫仁义礼智，此道之可道者也。然而仁不可以为义，而礼不可以为智，可道之不可常如此。……而道常不变，不可道之能常如此。”蒋锡昌说：“此道为世人所习称之道，即今人所谓‘道理’也，第一‘道’字应从是解。《广雅·释诂》二：‘道，说也’，第二‘道’字应从是解。‘常’乃真常不易之义，在文法上为区别词。……第三‘道’字即二十五章‘道法自然’之‘道’，……乃老子学说之总名也”。陈鼓应说：“第一个‘道’字是人们习称之道，即今人所谓‘道理’。第二个‘道’字，是指言说的意思。第三个‘道’字，是老子哲学上的专有名词，在本章它意指构成宇宙的实体与动力。……‘常道’之‘常’，为真常、永恒之意。……可以用言词表达的道，就不是常道”。\n",
    "-----------\n",
    "2.认为“道可道”中的第一个“道”，指的是宇宙万物的本原；“可道”中的“道”，指言说的意思；“常道”，指恒久存在的“道”。因此，“道可道，非常道”，指可以言说的“道”，就不是恒久存在的“道”。如张默生说：“‘道’，指宇宙的本体而言。……‘常’，是经常不变的意思。……可以说出来的道，便不是经常不变的道”。董平说：“第一个‘道’字与‘可道’之‘道’，内涵并不相同。第一个‘道’字，是老子所揭示的作为宇宙本根之‘道’；‘可道’之‘道’，则是‘言说’的意思。……这里的大意就是说：凡一切可以言说之‘道’，都不是‘常道’或永恒之‘道’”。汤漳平等说：“第一句中的三个‘道’，第一、三均指形上之‘道’，中间的‘道’作动词，为可言之义。……道可知而可行，但非恒久不变之道”。\n",
    "--------\n",
    "3.认为“道可道”中的第一个“道”，指的是宇宙万物的本原；“可道”中的“道”，指言说的意思；“常道”，则指的是平常人所讲之道、常俗之道。因此，“道可道，非常道”，指“道”是可以言说的，但它不是平常人所谓的道或常俗之道。如李荣说：“道者，虚极之理也。夫论虚极之理，不可以有无分其象，不可以上下格其真。……圣人欲坦兹玄路，开以教门，借圆通之名，目虚极之理，以理可名，称之可道。故曰‘吾不知其名，字之曰道’。非常道者，非是人间常俗之道也。人间常俗之道，贵之以礼义，尚之以浮华，丧身以成名，忘己而徇利。”司马光说：“世俗之谈道者，皆曰道体微妙，不可名言。老子以为不然，曰道亦可言道耳，然非常人之所谓道也。……常人之所谓道者，凝滞于物。”裘锡圭说：“到目前为止，可以说，几乎从战国开始，大家都把‘可道’之‘道’……看成老子所否定的，把‘常道’‘常名’看成老子所肯定的。这种看法其实有它不合理的地方，……‘道’是可以说的。《老子》这个《道经》第一章，开宗明义是要讲他的‘道’。第一个‘道’字，理所应当，也是讲他要讲的‘道’：道是可以言说的。……那么这个‘恒’字应该怎么讲？我认为很简单，‘恒’字在古代作定语用，经常是‘平常’‘恒常’的意思。……‘道’是可以言说的，但是我要讲的这个‘道’，不是‘恒道’，它不是一般人所讲的‘道’。\n",
    "''')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "1808df5e-f498-4fe2-8851-56f3f1661726",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "**文章总结：**\n",
      "\n",
      "1. 第一篇文章认为“道可道”的第一个“道”指的是道理，而“可道”的“道”指的是可以言说的内容，“常道”则代表恒常存在的道。文章引用了苏辙、蒋锡昌和陈鼓应的观点，强调了可以被表达的道理与恒久不变的道之间的区别。\n",
      "\n",
      "2. 第二篇文章则认为“道可道”的第一个“道”是宇宙本原，而“可道”的“道”仍然是指言说的意思，“常道”代表恒久存在的道。这篇文章的主要观点是：凡是可以被语言表达的道，都不是恒久存在的道，并引用了张默生、董平和汤漳平的思想。\n",
      "\n",
      "3. 第三篇文章进一步阐述了“道可道”的第一个“道”为宇宙万物的本原，而“可道”是可言说的意思。同时，第三篇文章的论点认为“常道”指的是世俗的常见之道。引用了李荣、司马光和裘锡圭的观点，强调虽然“道”可以言说，但并不是人间世俗的理解，体现了对深层道理的追求。\n",
      "\n",
      "**论点比较：**\n",
      "\n",
      "在三篇文章中，第二篇和第三篇对“道”的解释较为接近，更强调“道”与宇宙本源的联系，而第一篇更偏向道理的表达。比较而言，第三篇文章提出了更为丰富的论点，阐述了“常道”与世俗的对比，强调了道的特殊性和不可限量性，使得内容更具深度和广度。因此，第三篇文章的论点更强，有助于更深入理解“道”的内涵。\n"
     ]
    }
   ],
   "source": [
    "chat_result = llm.invoke(messages)\n",
    "print(chat_result.content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a3e40f9c-4ca8-471b-bea6-8c73e3efe2a5",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0cbd5e40-7a80-413a-ba4b-e196dc308cd6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "f73c609f-0dd0-4fab-854d-d30039c5817a",
   "metadata": {},
   "outputs": [],
   "source": [
    "##### 使用 FewShotPromptTemplate 类生成 Few-shot Prompt\n",
    "\n",
    "from langchain.prompts.prompt import PromptTemplate\n",
    "\n",
    "\n",
    "examples = [\n",
    "  {\n",
    "    \"question\": \"谁活得更久，穆罕默德·阿里还是艾伦·图灵？\",\n",
    "    \"answer\": \n",
    "\"\"\"\n",
    "这里需要进一步的问题吗：是的。\n",
    "追问：穆罕默德·阿里去世时多大了？\n",
    "中间答案：穆罕默德·阿里去世时74岁。\n",
    "追问：艾伦·图灵去世时多大了？\n",
    "中间答案：艾伦·图灵去世时41岁。\n",
    "所以最终答案是：穆罕默德·阿里\n",
    "\"\"\"\n",
    "  },\n",
    "  {\n",
    "    \"question\": \"craigslist的创始人是什么时候出生的？\",\n",
    "    \"answer\": \n",
    "\"\"\"\n",
    "这里需要进一步的问题吗：是的。\n",
    "追问：谁是craigslist的创始人？\n",
    "中间答案：Craigslist是由Craig Newmark创办的。\n",
    "追问：Craig Newmark是什么时候出生的？\n",
    "中间答案：Craig Newmark出生于1952年12月6日。\n",
    "所以最终答案是：1952年12月6日\n",
    "\"\"\"\n",
    "  },\n",
    "  {\n",
    "    \"question\": \"乔治·华盛顿的外祖父是谁？\",\n",
    "    \"answer\":\n",
    "\"\"\"\n",
    "这里需要进一步的问题吗：是的。\n",
    "追问：谁是乔治·华盛顿的母亲？\n",
    "中间答案：乔治·华盛顿的母亲是Mary Ball Washington。\n",
    "追问：Mary Ball Washington的父亲是谁？\n",
    "中间答案：Mary Ball Washington的父亲是Joseph Ball。\n",
    "所以最终答案是：Joseph Ball\n",
    "\"\"\"\n",
    "  },\n",
    "  {\n",
    "    \"question\": \"《大白鲨》和《皇家赌场》的导演是同一个国家的吗？\",\n",
    "    \"answer\":\n",
    "\"\"\"\n",
    "这里需要进一步的问题吗：是的。\n",
    "追问：谁是《大白鲨》的导演？\n",
    "中间答案：《大白鲨》的导演是Steven Spielberg。\n",
    "追问：Steven Spielberg来自哪里？\n",
    "中间答案：美国。\n",
    "追问：谁是《皇家赌场》的导演？\n",
    "中间答案：《皇家赌场》的导演是Martin Campbell。\n",
    "追问：Martin Campbell来自哪里？\n",
    "中间答案：新西兰。\n",
    "所以最终答案是：不是\n",
    "\"\"\"\n",
    "  }\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "6e49e450-8e5d-4139-818a-dbaa2668e071",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: 谁活得更久，穆罕默德·阿里还是艾伦·图灵？\n",
      "\n",
      "这里需要进一步的问题吗：是的。\n",
      "追问：穆罕默德·阿里去世时多大了？\n",
      "中间答案：穆罕默德·阿里去世时74岁。\n",
      "追问：艾伦·图灵去世时多大了？\n",
      "中间答案：艾伦·图灵去世时41岁。\n",
      "所以最终答案是：穆罕默德·阿里\n",
      "\n"
     ]
    }
   ],
   "source": [
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"question\", \"answer\"],\n",
    "    template=\"Question: {question}\\n{answer}\"\n",
    ")\n",
    "\n",
    "# **examples[0] 是将examples[0] 字典的键值对（question-answer）解包并传递给format，作为函数参数\n",
    "print(example_prompt.format(**examples[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "b1eb9af0-ecba-46a2-bc9a-0f8f0420cb94",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: 谁活得更久，穆罕默德·阿里还是艾伦·图灵？\n",
      "Answer: \n",
      "这里需要进一步的问题吗：是的。\n",
      "追问：穆罕默德·阿里去世时多大了？\n",
      "中间答案：穆罕默德·阿里去世时74岁。\n",
      "追问：艾伦·图灵去世时多大了？\n",
      "中间答案：艾伦·图灵去世时41岁。\n",
      "所以最终答案是：穆罕默德·阿里\n",
      "\n"
     ]
    }
   ],
   "source": [
    "def print_info(question, answer):\n",
    "    print(f\"Question: {question}\")\n",
    "    print(f\"Answer: {answer}\")\n",
    "\n",
    "print_info(**examples[0]) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "25335766-7123-45f4-924b-58e8992fea67",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "56abc479-fc2b-494c-bf46-3e44fef7e684",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: 谁活得更久，穆罕默德·阿里还是艾伦·图灵？\n",
      "\n",
      "这里需要进一步的问题吗：是的。\n",
      "追问：穆罕默德·阿里去世时多大了？\n",
      "中间答案：穆罕默德·阿里去世时74岁。\n",
      "追问：艾伦·图灵去世时多大了？\n",
      "中间答案：艾伦·图灵去世时41岁。\n",
      "所以最终答案是：穆罕默德·阿里\n",
      "\n",
      "\n",
      "Question: craigslist的创始人是什么时候出生的？\n",
      "\n",
      "这里需要进一步的问题吗：是的。\n",
      "追问：谁是craigslist的创始人？\n",
      "中间答案：Craigslist是由Craig Newmark创办的。\n",
      "追问：Craig Newmark是什么时候出生的？\n",
      "中间答案：Craig Newmark出生于1952年12月6日。\n",
      "所以最终答案是：1952年12月6日\n",
      "\n",
      "\n",
      "Question: 乔治·华盛顿的外祖父是谁？\n",
      "\n",
      "这里需要进一步的问题吗：是的。\n",
      "追问：谁是乔治·华盛顿的母亲？\n",
      "中间答案：乔治·华盛顿的母亲是Mary Ball Washington。\n",
      "追问：Mary Ball Washington的父亲是谁？\n",
      "中间答案：Mary Ball Washington的父亲是Joseph Ball。\n",
      "所以最终答案是：Joseph Ball\n",
      "\n",
      "\n",
      "Question: 《大白鲨》和《皇家赌场》的导演是同一个国家的吗？\n",
      "\n",
      "这里需要进一步的问题吗：是的。\n",
      "追问：谁是《大白鲨》的导演？\n",
      "中间答案：《大白鲨》的导演是Steven Spielberg。\n",
      "追问：Steven Spielberg来自哪里？\n",
      "中间答案：美国。\n",
      "追问：谁是《皇家赌场》的导演？\n",
      "中间答案：《皇家赌场》的导演是Martin Campbell。\n",
      "追问：Martin Campbell来自哪里？\n",
      "中间答案：新西兰。\n",
      "所以最终答案是：不是\n",
      "\n",
      "\n",
      "Question: 玛丽·波尔·华盛顿的父亲是谁?\n"
     ]
    }
   ],
   "source": [
    "# 导入 FewShotPromptTemplate 类\n",
    "from langchain.prompts.few_shot import FewShotPromptTemplate\n",
    "\n",
    "# 创建一个 FewShotPromptTemplate 对象\n",
    "few_shot_prompt = FewShotPromptTemplate(\n",
    "    examples=examples,           # 使用前面定义的 examples 作为范例\n",
    "    example_prompt=example_prompt, # 使用前面定义的 example_prompt 作为提示模板\n",
    "    suffix=\"Question: {input}\",    # 后缀模板，其中 {input} 会被替换为实际输入\n",
    "    input_variables=[\"input\"]     # 定义输入变量的列表\n",
    ")\n",
    "\n",
    "# 使用给定的输入格式化 prompt，并打印结果\n",
    "# 这里的 {input} 将被 \"玛丽·波尔·华盛顿的父亲是谁?\" 替换\n",
    "print(few_shot_prompt.format(input=\"玛丽·波尔·华盛顿的父亲是谁?\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5b2be99-1bfc-44b5-814c-c6658287055b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a3aea73b-b42d-4b5d-826a-2b4314267523",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "da9e0258-1bc9-4084-b35c-e08832a02500",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入需要的模块和类\n",
    "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n",
    "from langchain.vectorstores import Chroma\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n",
    "\n",
    "# 定义一个提示模板\n",
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"input\", \"output\"],     # 输入变量的名字\n",
    "    template=\"Input: {input}\\nOutput: {output}\",  # 实际的模板字符串\n",
    ")\n",
    "\n",
    "# 这是一个假设的任务示例列表，用于创建反义词\n",
    "examples = [\n",
    "    {\"input\": \"happy\", \"output\": \"sad\"},\n",
    "    {\"input\": \"tall\", \"output\": \"short\"},\n",
    "    {\"input\": \"energetic\", \"output\": \"lethargic\"},\n",
    "    {\"input\": \"sunny\", \"output\": \"gloomy\"},\n",
    "    {\"input\": \"windy\", \"output\": \"calm\"},\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "f8dd7f76-904b-43f4-9c21-65671b4b824b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 从给定的示例中创建一个语义相似性选择器\n",
    "example_selector = SemanticSimilarityExampleSelector.from_examples(\n",
    "    examples,                          # 可供选择的示例列表\n",
    "    OpenAIEmbeddings(\n",
    "        openai_api_key=\"sk-y7DHfp9fzuCxOVm2158638099f9541D3833aB4F4Ed674aCf\",\n",
    "        openai_api_base=\"https://vip.apiyi.com/v1\",\n",
    "        model=\"text-embedding-ada-002\",),                # 用于生成嵌入向量的嵌入类，用于衡量语义相似性\n",
    "    Chroma,                            # 用于存储嵌入向量并进行相似性搜索的 VectorStore 类\n",
    "    k=1                                # 要生成的示例数量\n",
    ")\n",
    "\n",
    "# 创建一个 FewShotPromptTemplate 对象\n",
    "similar_prompt = FewShotPromptTemplate(\n",
    "    example_selector=example_selector,  # 提供一个 ExampleSelector 替代示例\n",
    "    example_prompt=example_prompt,      # 前面定义的提示模板\n",
    "    prefix=\"Give the antonym of every input\", # 前缀模板\n",
    "    suffix=\"Input: {adjective}\\nOutput:\",     # 后缀模板\n",
    "    input_variables=[\"adjective\"],           # 输入变量的名字\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "be335153-cf5c-4960-9079-59d024151faf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Give the antonym of every input\n",
      "\n",
      "Input: happy\n",
      "Output: sad\n",
      "\n",
      "Input: worried\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "print(similar_prompt.format(adjective=\"worried\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "e7eb53e3-2dad-4c49-ba20-14b73d6254eb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Give the antonym of every input\n",
      "\n",
      "Input: tall\n",
      "Output: short\n",
      "\n",
      "Input: long\n",
      "Output:\n",
      "Give the antonym of every input\n",
      "\n",
      "Input: windy\n",
      "Output: calm\n",
      "\n",
      "Input: rain\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "print(similar_prompt.format(adjective=\"long\"))\n",
    "print(similar_prompt.format(adjective=\"rain\"))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "56f76e36-980f-4867-8897-ddf9f9db8eca",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ffa21334-426b-4bc5-95a4-343011aadece",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "ff9d23c8-1665-48bf-9a07-042ee068ea4b",
   "metadata": {},
   "outputs": [],
   "source": [
    "examples = [\n",
    "    {\"input\": \"happy\", \"output\": \"sad\"},\n",
    "    {\"input\": \"tall\", \"output\": \"short\"},\n",
    "    {\"input\": \"energetic\", \"output\": \"lethargic\"},\n",
    "    {\"input\": \"sunny\", \"output\": \"gloomy\"},\n",
    "    {\"input\": \"windy\", \"output\": \"calm\"},\n",
    "]\n",
    "\n",
    "example_prompt = PromptTemplate(\n",
    "    input_variables = [\"input\", \"output\"],\n",
    "    template = \"Input：{input}\\t\\tOutput：{output}\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "bae2fe6f-a643-4b87-a75d-194e7dd35ed9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input：happy\t\tOutput：sad\n",
      "input_variables=['input', 'output'] input_types={} partial_variables={} template='Input：{input}\\t\\tOutput：{output}'\n",
      "Input：happy\t\tOutput：sad\n",
      "\n",
      "Input：tall\t\tOutput：short\n",
      "\n",
      "Input：energetic\t\tOutput：lethargic\n",
      "\n",
      "Input：sunny\t\tOutput：gloomy\n",
      "\n",
      "Input：windy\t\tOutput：calm\n",
      "\n",
      "Input: worried\n"
     ]
    }
   ],
   "source": [
    "from langchain.prompts.few_shot import FewShotPromptTemplate\n",
    "\n",
    "print(example_prompt.format(**examples[0]))\n",
    "print(example_prompt)\n",
    "\n",
    "# 使用FewShotPromptTemplate生成Few-shot Prompt\n",
    "few_shot_prompt= FewShotPromptTemplate(\n",
    "    examples=examples,           # 使用前面定义的 examples 作为范例\n",
    "    example_prompt=example_prompt, # 使用前面定义的 example_prompt 作为提示模板\n",
    "    suffix=\"Input: {input}\",    # 后缀模板，其中 {input} 会被替换为实际输入\n",
    "    input_variables=[\"input\"]     # 定义输入变量的列表\n",
    ")\n",
    "\n",
    "print(few_shot_prompt.format(input = \"worried\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a5e1a45f-d710-43f1-a95b-db739fc8a644",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Give the antonym of every input\n",
      "\n",
      "Input：happy\t\tOutput：sad\n",
      "\n",
      "Input: worried\t\tOutput:\n",
      "Give the antonym of every input\n",
      "\n",
      "Input：tall\t\tOutput：short\n",
      "\n",
      "Input: long\t\tOutput:\n",
      "Give the antonym of every input\n",
      "\n",
      "Input：windy\t\tOutput：calm\n",
      "\n",
      "Input: rain\t\tOutput:\n"
     ]
    }
   ],
   "source": [
    "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n",
    "from langchain.vectorstores import Chroma    # 向量数据库\n",
    "from langchain_openai import OpenAIEmbeddings    # embedding\n",
    "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n",
    "\n",
    "# 从给定的示例中创建一个语义相似性选择器\n",
    "example_selector = SemanticSimilarityExampleSelector.from_examples(\n",
    "    examples,                          # 可供选择的示例列表\n",
    "    # OpenAIEmbeddings(),                # 用于生成嵌入向量的嵌入类，用于衡量语义相似性\n",
    "    \n",
    "    OpenAIEmbeddings(\n",
    "        openai_api_key=\"sk-y7DHfp9fzuCxOVm2158638099f9541D3833aB4F4Ed674aCf\",\n",
    "        openai_api_base=\"https://vip.apiyi.com/v1\",\n",
    "        model=\"text-embedding-ada-002\",),                # 用于生成嵌入向量的嵌入类，用于衡量语义相似性\n",
    "    Chroma,                            # 用于存储嵌入向量并进行相似性搜索的 VectorStore 类\n",
    "    k=1                                # 要生成的示例数量\n",
    ")\n",
    "\n",
    "# 创建一个 FewShotPromptTemplate 对象\n",
    "similar_prompt = FewShotPromptTemplate(\n",
    "    example_selector=example_selector,  # 提供一个 ExampleSelector 替代示例\n",
    "    example_prompt=example_prompt,      # 前面定义的提示模板\n",
    "    prefix=\"Give the antonym of every input\", # 前缀模板\n",
    "    suffix=\"Input: {adjective}\\t\\tOutput:\",     # 后缀模板\n",
    "    input_variables=[\"adjective\"],           # 输入变量的名字\n",
    ")\n",
    "\n",
    "print(similar_prompt.format(adjective=\"worried\"))\n",
    "print(similar_prompt.format(adjective=\"long\"))\n",
    "print(similar_prompt.format(adjective=\"rain\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01e35a91-5039-4de7-99ee-a1a2f75f1291",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
